<template>
  <demo-content :title="title">
    <p></p>
    <canvas ref="canvasRef" width="300" height="300"></canvas>
    <canvas ref="canvasClockRef" width="300" height="300"></canvas>
    <canvas ref="canvasImageRef" width="800" height="200"></canvas>
  </demo-content>
</template>

<script setup lang="ts">
import { onMounted, ref } from "vue";
import sunUrl from "@/assets/sun.png";
import earthUrl from "@/assets/earth.png";
import moonUrl from "@/assets/moon.png";
import parkUrl from "@/assets/park.jpg";

const title = "动画";
// 指定组件上的属性
defineOptions({ title });

const canvasRef = ref<HTMLCanvasElement>();
const canvasClockRef = ref<HTMLCanvasElement>();
const canvasImageRef = ref<HTMLCanvasElement>();

function solarSystemInit() {
  const canvas = canvasRef.value!;
  const ctx = canvas.getContext("2d")!;
  const sun = new Image();
  const earth = new Image();
  const sunEarthDist = 110;
  const moon = new Image();
  const earthMoonDist = 18;
  sun.src = sunUrl;
  earth.src = earthUrl;
  moon.src = moonUrl;
  function update() {
    ctx.drawImage(sun, 0, 0, 300, 300);
    // 绘制地球
    const now = new Date();
    ctx.save();
    ctx.translate(150, 150);
    const earthRunAngle =
      ((now.getSeconds() + now.getMilliseconds() / 1000) / 60) * 2 * Math.PI;
    ctx.rotate(earthRunAngle);

    ctx.translate(sunEarthDist, 0);
    ctx.drawImage(earth, -12, -12);
    // 绘制月亮
    ctx.save();
    const moonRunAngle = earthRunAngle * 5;
    ctx.rotate(moonRunAngle);
    ctx.drawImage(moon, earthMoonDist, 0);
    ctx.restore();
    ctx.restore();
  }
  return update;
}
function clockInit() {
  const canvas = canvasClockRef.value!;
  const ctx = canvas.getContext("2d")!;
  const update = () => {
    ctx.clearRect(0, 0, 300, 300);
    ctx.save();
    ctx.translate(150, 150);
    // 绘制外环
    ctx.save();
    ctx.beginPath();
    ctx.strokeStyle = "#3d5ea0";
    ctx.lineWidth = 10;
    ctx.arc(0, 0, 130, 0, 2 * Math.PI);
    ctx.stroke();
    ctx.restore();
    // 绘制时针刻度
    ctx.save();
    ctx.beginPath();
    ctx.lineWidth = 8;
    for (let i = 0; i < 12; i++) {
      ctx.moveTo(0, 100);
      ctx.lineTo(0, 120);
      ctx.stroke();
      ctx.rotate((Math.PI * 2) / 12);
    }
    ctx.restore();
    // 绘制分钟刻度
    ctx.save();
    ctx.lineWidth = 3;
    ctx.beginPath();
    for (let i = 0; i < 60; i++) {
      ctx.moveTo(0, 113);
      ctx.lineTo(0, 120);
      ctx.stroke();
      ctx.rotate((Math.PI * 2) / 60);
    }
    ctx.restore();
    const now = new Date();
    // 绘制时针
    ctx.save();
    ctx.rotate(((now.getHours() % 12) / 12) * Math.PI * 2 - Math.PI / 2);
    ctx.lineWidth = 12;
    ctx.lineCap = "round";
    ctx.beginPath();
    ctx.moveTo(-20, 0);
    ctx.lineTo(70, 0);
    ctx.stroke();
    ctx.restore();
    // 绘制分钟
    ctx.save();
    ctx.rotate((now.getMinutes() / 60) * Math.PI * 2 - Math.PI / 2);
    ctx.lineWidth = 8;
    ctx.lineCap = "round";
    ctx.beginPath();
    ctx.moveTo(-23, 0);
    ctx.lineTo(85, 0);
    ctx.stroke();
    ctx.restore();
    // 绘制秒针
    ctx.save();
    ctx.rotate((now.getSeconds() / 60) * Math.PI * 2 - Math.PI / 2);
    ctx.lineWidth = 5;
    ctx.strokeStyle = "red";
    ctx.fillStyle = "red";
    ctx.beginPath();
    ctx.moveTo(-25, 0);
    ctx.lineTo(90, 0);
    ctx.stroke();
    ctx.beginPath();
    ctx.arc(0, 0, 8, 0, Math.PI * 2);
    ctx.fill();
    ctx.beginPath();
    ctx.arc(92.5, 0, 5, 0, Math.PI * 2);
    ctx.stroke();
    ctx.restore();
    ctx.restore();
  };
  return update;
}
function imageInit() {
  const canvas = canvasImageRef.value!;
  const ctx = canvas.getContext("2d")!;
  const image = new Image();
  image.src = parkUrl;
  let loaded = false;
  let startX = 0;
  image.onload = () => {
    loaded = true;
  };
  const update = () => {
    if (!loaded) return;
    if (startX < 0) startX += image.width;
    ctx.drawImage(
      image,
      startX,
      0,
      image.width - startX,
      image.height,
      0,
      0,
      image.width - startX,
      image.height
    );
    if (image.width - startX < canvas.width) {
      ctx.drawImage(
        image,
        0,
        0,
        canvas.width - (image.width - startX),
        image.height,
        image.width - startX,
        0,
        canvas.width - (image.width - startX),
        image.height
      );
    }
    startX -= 2;
  };
  return update;
}
onMounted(() => {
  const solarSystemUpdate = solarSystemInit();
  const clockUpdate = clockInit();
  const imageUpdate = imageInit();
  function update() {
    solarSystemUpdate();
    // clockUpdate();
    window.requestAnimationFrame(update);
  }
  window.requestAnimationFrame(update);
  clockUpdate();
  setInterval(clockUpdate, 1000);
  setInterval(imageUpdate, 100);
});
</script>

<style src="./default.css" scoped></style>
